#include <windows.h>	//
#include <gl/gl.h>		// better done in renderer
#include <assert.h>

#include "globals.h"
#include "point2.h"
#include "defines.h"
#include "fx.h"
#include "source.h"
#include "io.h"
#include "texture.h"
#include "rect.h"
#include "source.h"
#include "animation.h"
#include "audio.h"
#include "character.h"
#include "object.h"
#include "globals.h"

float D_TOUCH =0.1f;
float STAND_TEST =0.5f;		// double d touch
float LOGIC_CYCLE_TIME =30;
float MAX_LOGIC_CYCLE_TIME =30;

Point2 V_UP;
Point2 V_DOWN;
Point2 V_STAND_TEST;
Point2 V_NULL;
Point2 V_TMP;
Rect RECT_TMP;
Fx* FX_SHOT;
Fx* FX_RIK;
Fx* FX_BANG;
Source** SRC_HIT;
int src_hit_num =0;
Source** SRC_RIK;
Source* SRC_SHOTGUN;
Source* SRC_NOAMMO;
Source* SRC_GROUND_HIT;
Source* SRC_STEP_GRAVEL;
Source* SRC_LAND_CONCRETE;
Source* SRC_STEP_CONCRETE;

Texture* main_menu;
Texture* start_game;
Texture* exit_game;
Texture* cont_game;
Rect R_MENU;
Rect R_BUTTON;

int initGlobals(){

	V_UP.x =0;
	V_UP.y =1;

	V_DOWN.x =0;
	V_DOWN.y =-1;

	V_STAND_TEST.x =0;
	V_STAND_TEST.y =-STAND_TEST;

	V_NULL.x =0;
	V_NULL.y =0;

	FX_RIK =loadFx("ric.txt", false);	//? hardcoded
	assert(FX_RIK);

	FX_BANG =loadFx("bang.txt", false);	//? hardcoded
	assert(FX_BANG);

	FX_SHOT =loadFx("shot.txt", false);	//? hardcoded
	assert(FX_RIK);

	SRC_STEP_GRAVEL =loadSource("step_gravel.txt", false);	//?
	assert(SRC_STEP_GRAVEL);
	SRC_GROUND_HIT =loadSource("land1.txt", false);	//?
	assert(SRC_GROUND_HIT);

	SRC_STEP_CONCRETE =loadSource("step_pavement.txt", false);	//?
	assert(SRC_STEP_CONCRETE);
	SRC_LAND_CONCRETE =loadSource("land_pavement.txt", false);	//?
	assert(SRC_LAND_CONCRETE);

	if(!loadSources("hits.txt", false, &SRC_HIT, &src_hit_num)){

		return 0;
	}
	
	SRC_RIK =new Source*[2];
	SRC_RIK[0] =loadSource("rik.txt", false);
	assert(SRC_RIK[0]);
	SRC_RIK[1] =loadSource("rik1.txt", false);
	assert(SRC_RIK[1]);

	SRC_SHOTGUN =loadSource("shotgun.txt", false);
	assert(SRC_SHOTGUN);
	SRC_NOAMMO =loadSource("noammo.txt", false);
	assert(SRC_NOAMMO);

	R_MENU.xLo =0;
	R_MENU.yLo =0;
	R_MENU.xHi =800;
	R_MENU.yHi =600;

	R_BUTTON.xLo =0;
	R_BUTTON.yLo =0;
	R_BUTTON.xHi =160;
	R_BUTTON.yHi =40;

	return 1;
}

bool loadMenu(){

	main_menu =loadTexture("mmenu.txt", false);
	assert(main_menu);
	main_menu->texDx =0;
	main_menu->texDy =0;
	start_game =loadTexture("startg.txt", false);
	assert(start_game);
	start_game->texDx =0;
	start_game->texDy =0;
	exit_game =loadTexture("exitg.txt", false);
	assert(exit_game);
	exit_game->texDx =0;
	exit_game->texDy =0;
	cont_game =loadTexture("contg.txt", false);
	assert(cont_game->tex);
	cont_game->texDx =0;
	cont_game->texDy =0;

	return true;
}

bool releaseMenu(){

	glDeleteTextures(1, &(main_menu->tex));
	delete main_menu;
	main_menu =NULL;
	glDeleteTextures(1, &(start_game->tex));
	delete start_game;
	start_game =NULL;
	glDeleteTextures(1, &(exit_game->tex));
	delete exit_game;
	exit_game =NULL;
	glDeleteTextures(1, &(cont_game->tex));
	delete cont_game;
	cont_game =NULL;

	return true;
}

void releaseGlobals(){

	int i;

	FX_RIK->animation->release();
	delete FX_RIK;
	FX_RIK =NULL;

	FX_SHOT->animation->release();
	delete FX_SHOT;
	FX_SHOT =NULL;

	FX_BANG->animation->release();
	delete FX_BANG;
	FX_BANG =NULL;


	if(SRC_RIK){
//		audio.deleteBuffer(&SRC_RIK[0]->buffer);
		SRC_RIK[0]->release();
		delete SRC_RIK[0];
		SRC_RIK[0] =NULL;
//		audio.deleteBuffer(&SRC_RIK[1]->buffer);
		SRC_RIK[1]->release();
		delete SRC_RIK[1];
		SRC_RIK[1] =NULL;
		delete SRC_RIK;
		SRC_RIK =NULL;
	}

	for(i=0; i<src_hit_num; i++){

		delete SRC_HIT[i];
		SRC_HIT[i] =NULL;
	}
	delete[] SRC_HIT;
	SRC_HIT =NULL;

//	audio.deleteBuffer(&SRC_SHOTGUN->buffer);
	SRC_SHOTGUN->release();
	delete SRC_SHOTGUN;
	SRC_SHOTGUN =NULL;

	SRC_NOAMMO->release();
	delete SRC_NOAMMO;
	SRC_NOAMMO =NULL;

	SRC_GROUND_HIT->release();
	delete SRC_GROUND_HIT;
	SRC_GROUND_HIT =NULL;
}

Source* createSource(int sound){

	Audio* audio =Audio::Instance();
	Source* s =NULL;
	s =new Source;

	switch(sound){
	case SND_STEP_GROUND:
		*s =*SRC_STEP_GRAVEL;
		break;
	case SND_STEP_CONCRETE:
		*s =*SRC_STEP_CONCRETE;
		break;
	case SND_LAND_CONCRETE:
		*s =*SRC_LAND_CONCRETE;
		break;
	default:
		delete s;
		s =NULL;
		break;
	}

	if(s)
		audio->genSource(&(s->id));

	return s;
}

Source* createSource(int state, int material){

	Source* s =NULL;
	Audio* audio =Audio::Instance();

	switch(state){
	case STATE_MOVE:

		switch(material){
		case MAT_GROUND:
			s =new Source;
			*s =*SRC_STEP_GRAVEL;
			audio->genSource(&(s->id));
			break;
		case MAT_CONCRETE:
			s =new Source;
			*s =*SRC_STEP_CONCRETE;
			audio->genSource(&(s->id));
			break;
		}
		break;

	case STATE_FALL:
		switch(material){
		case MAT_GROUND:
			s =new Source;
			*s =*SRC_GROUND_HIT;
			audio->genSource(&(s->id));
			break;
		case MAT_CONCRETE:
			s =new Source;
			*s =*SRC_LAND_CONCRETE;
			audio->genSource(&(s->id));
			break;
		}
		break;
	}

	return s;
}

void srcPlay(Character* character){

	Audio* audio =Audio::Instance();
	Source* source;

	source =character->cur_animation->sources[character->cur_animation->cur_frame];

	if(!source)
		return;

	if(audio->isPlaying(source->id)){

		audio->stopSource(source->id);
//		return;
	}

	audio->setSource(source->id, source->buffer, character->position->x, character->position->y, 0, source->gain, source->loop);
	audio->playSource(source->id);
}

// returns pointer to ricochet source
// randomly generated
Source* createRikSource(){

	Audio* audio =Audio::Instance();
	Source* s =new Source;
	int rnd =rand()%2;
	*s =*SRC_RIK[rnd];
	audio->genSource(&(s->id));
	return s;
}

Source* createHitSource(){

	Audio* audio =Audio::Instance();
	Source* s =new Source;
	int rnd =rand()%src_hit_num;
	*s =*SRC_HIT[rnd];
	audio->genSource(&(s->id));
	return s;
}

Source* createGroundSource(){

	Audio* audio =Audio::Instance();
	Source* s =new Source;
	*s =*SRC_GROUND_HIT;
	audio->genSource(&(s->id));
	return s;
}

void srcPlay(Object* object, Character* character){

	Audio* audio =Audio::Instance();
	Source** source;
	Source* src_tmp=NULL;
	source =&src_tmp;

	if(!object)
		return;

	switch(character->state){

	case STATE_MOVE:

		if( (character->cur_animation->cur_frame +1)%(character->cur_animation->nFrames/2) ==0){	//? hadrcoded
			 
			if(character->src_move==NULL){

				source =&character->src_move;
			}
		}
		else{
			if(character->src_move!=NULL){
				audio->stopSource(character->src_move->id);
				delete character->src_move;
				character->src_move =NULL;
			}
		}
		break;
	case STATE_FALL:

		if(character->src_fall==NULL){

			source =&character->src_fall;
		}
		else{

			if(!audio->isPlaying(character->src_fall->id)){
				delete character->src_fall;
				character->src_fall =NULL;
			}
			else{
				audio->stopSource(character->src_fall->id);
				delete character->src_fall;
				character->src_fall =NULL;
			}
		}

		break;
	}

	if(source==&src_tmp)
		return;

	*source =createSource(character->state, object->material);
	if(!(*source))
		return;

	audio->setSource((*source)->id, (*source)->buffer, character->position->x, character->position->y, 0, (*source)->gain, (*source)->loop);
	audio->playSource((*source)->id);
}
